package com.cnt.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.cnt.dao.*;
import com.cnt.dto.MoneyDTO;
import com.cnt.entity.*;
import com.cnt.service.DonationRecordsService;
import com.cnt.util.*;
import com.cnt.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigInteger;
import java.text.DecimalFormat;
import java.util.*;

@Service
public class DonationRecordsServiceImpl implements DonationRecordsService {

    @Autowired
    private DonationRecordsDao donationRecordsDao;
    @Autowired
    private MoneyDao moneyDao;
    @Autowired
    private LogUtil logUtil;
    @Autowired
    private DonationsDao donationsDao;
    @Autowired
    private MoneyLogDao moneyLogDao;
    @Autowired
    private ReportDao reportDao;

    @Override
    public ResultVo<List<DonationRecords>> getDonationRecordsByUserId(Integer userId) {
        return new ResultVo<>(0, "查询成功", donationRecordsDao.getByUserId(userId));
    }

    @Override
    public ResultVo<List<DonationRecords>> getDonationRecords() {
        return new ResultVo<>(0, "查询成功", donationRecordsDao.selectList(null));
    }

    @Override
    public ResultVo<List<MoneyLog>> getMoneyLog() {
        return new ResultVo<>(0, "查询成功", moneyLogDao.selectList(null));
    }

    @Override
    public ResultVo<String> recharge(MoneyDTO moneyDTO) {
        double amount = moneyDTO.getAmount();
        if (amount == 0)return new ResultVo<>(5,"请先输入充值金额",null);
        Integer userId = moneyDTO.getUserId();
        LambdaUpdateWrapper<Money> luw = Wrappers.lambdaUpdate();
        luw.eq(Money::getUserId, userId)
                .setSql("money = money + " + amount);
        int i = moneyDao.update(null, luw);
        if (i != 1) {
            return new ResultVo<>(4, "系统繁忙，请稍后再试", null);
        }
        String transferId = generateRandomString();
        logUtil.recordMoneyLog(1, userId, transferId, "ID为" + userId + "的用户充值成功，金额为" + amount);
        return new ResultVo<>(0, "充值成功", null);
    }

    @Override
    public ResultVo<String> withdraw(MoneyDTO moneyDTO) {
        double amount = moneyDTO.getAmount();
        Integer userId = moneyDTO.getUserId();
        LambdaUpdateWrapper<Money> luw = Wrappers.lambdaUpdate();
        luw.eq(Money::getUserId, userId)
                .setSql("money = money - " + amount);
        int i = moneyDao.update(null, luw);
        if (i != 1) {
            return new ResultVo<>(1, "系统繁忙，请稍后再试", null);
        }
        String transferId = generateRandomString();
        logUtil.recordMoneyLog(2, userId, transferId, "ID为" + userId + "的用户提现成功，金额为" + amount);

        return new ResultVo<>(0, "提现成功", null);
    }

    @Override
    public ResultVo<String> contribution(MoneyDTO moneyDTO) {
        double amount = moneyDTO.getAmount();
        LambdaUpdateWrapper<Money> luw = Wrappers.lambdaUpdate();
        luw.eq(Money::getUserId, moneyDTO.getUserId())
                .ge(Money::getMoney, amount)
                .setSql("money = money - " + amount);
        int i = moneyDao.update(null, luw);
        if (i != 1) {
            return new ResultVo<>(1, "余额不足，捐款失败", null);
        }
        LambdaUpdateWrapper<Donations> luw2 = Wrappers.lambdaUpdate();
        luw2.eq(Donations::getDonationId, moneyDTO.getDonationId())
                .setSql("donated_amount = donated_amount + " + amount);
        donationsDao.update(null, luw2);
        logUtil.recordDonation(moneyDTO.getDonationId(), moneyDTO.getUserId(), moneyDTO.getAmount());
        return new ResultVo<>(0, "捐款成功", null);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)//添加为事务
    public ResultVo<String> donationRefund(MoneyDTO moneyDTO) {
        int donationId = moneyDTO.getDonationId();
        Donations donations = donationsDao.selectById(donationId);
        double donatedAmount = donations.getDonatedAmount();
        if (donatedAmount == 0){
            return new ResultVo<>(1,"该募捐活动还没募捐到钱",null);
        }
        double residue = donatedAmount - donations.getExpenseAmount(); //剩余钱
        DecimalFormat decimalFormat = new DecimalFormat("#.00");
        String formattedResult = decimalFormat.format(residue / donatedAmount);
        double bl = Double.parseDouble(formattedResult);

        List<DonationRecords> donationRecordsList = donationRecordsDao.getByDonationId(donationId);
        for (DonationRecords donationRecords : donationRecordsList) {
            Integer userId = donationRecords.getUserId();
            double refund = donationRecords.getDonationAmount() * bl;
            String strResult = decimalFormat.format(refund);
            double refundAmount = Double.parseDouble(strResult);
            LambdaUpdateWrapper<Money> luw = Wrappers.lambdaUpdate();
            luw.eq(Money::getUserId, userId)
                    .setSql("money = money + " + refundAmount);
            moneyDao.update(null, luw);
            String transferId = generateRandomString();
            LambdaUpdateWrapper<Report> luw1 = new LambdaUpdateWrapper<>();
            luw1.eq(Report::getDonationId,donationId)
                    .set(Report::getRefundAmount,donatedAmount);
            reportDao.update(null,luw1);
            logUtil.recordMoneyLog(3, userId, transferId, "ID为" + userId + "的用户收到了捐赠回退，金额为" + refundAmount);
        }
        return new ResultVo<>(0, "回退成功", null);

    }

    @Override
    public ResultVo<List<DonationRecords>> getDonationRecords(Integer donationId) {
        List<String> list = new ArrayList<>();
        List<DonationRecords> donationRecordsList = donationRecordsDao.getByDonationId(donationId);
        if (donationRecordsList == null) {
            return new ResultVo<>(1, "该募捐活动还未有人捐款", null);
        }
        return new ResultVo<>(0, "查询成功", donationRecordsList);
    }

    @Override
    public ResultVo<Map<Integer, Double>> chartDataDonation(Integer year) {
        List<DonationRecords> dataByYear = donationRecordsDao.selectByYear(year);
        Map<Integer, Double> dataByMonth = new HashMap<>();
        for (DonationRecords donationRecord : dataByYear) {
            int k = donationRecord.getDonationTime().getMonth() + 1;
            dataByMonth.merge(k, donationRecord.getDonationAmount(), Double::sum);
        }
        return new ResultVo<>(0, "查询成功", dataByMonth);
    }

    @Override
    public ResultVo<List<Map<String, Object>>> rechargeByUserId(Integer userId) {
        QueryWrapper<MoneyLog> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        wrapper.eq("flag", 1);
        List<MoneyLog> logList = moneyLogDao.selectList(wrapper);
        List<Map<String, Object>> list = new ArrayList<>();
        for (MoneyLog moneyLog : logList) {
            Map<String, Object> map = new TreeMap<>();
            map.put("moneyLogId", moneyLog.getMoneyLogId());
            map.put("transferId", moneyLog.getTransferId());
            map.put("time", moneyLog.getTime());
            map.put("message", moneyLog.getMessage());
            list.add(map);
        }
        return new ResultVo<>(0, "查询成功", list);
    }

    @Override
    public ResultVo<List<Map<String, Object>>> withdrawByUserId(Integer userId) {
        QueryWrapper<MoneyLog> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        wrapper.eq("flag", 2);
        List<MoneyLog> logList = moneyLogDao.selectList(wrapper);
        List<Map<String, Object>> list = new ArrayList<>();
        for (MoneyLog moneyLog : logList) {
            Map<String, Object> map = new TreeMap<>();
            map.put("moneyLogId", moneyLog.getMoneyLogId());
            map.put("transferId", moneyLog.getTransferId());
            map.put("time", moneyLog.getTime());
            map.put("message", moneyLog.getMessage());
            list.add(map);
        }
        return new ResultVo<>(0, "查询成功", list);
    }

    @Override
    public ResultVo<List<Map<String, Object>>> refundByUserId(Integer userId) {
        QueryWrapper<MoneyLog> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id", userId);
        wrapper.eq("flag", 3);
        List<MoneyLog> logList = moneyLogDao.selectList(wrapper);
        List<Map<String, Object>> list = new ArrayList<>();
        for (MoneyLog moneyLog : logList) {
            Map<String, Object> map = new TreeMap<>();
            map.put("moneyLogId", moneyLog.getMoneyLogId());
            map.put("transferId", moneyLog.getTransferId());
            map.put("time", moneyLog.getTime());
            map.put("message", moneyLog.getMessage());
            list.add(map);
        }
        return new ResultVo<>(0, "查询成功", list);
    }

    @Override
    public ResultVo<Double> getMoneyInfo(Integer userId) {
        Money money = moneyDao.selectByUserId(userId);
        return new ResultVo<>(0, "查询成功", money.getMoney());
    }


    public static String generateRandomString() {
        Random random = new Random();
        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < 19; i++) {
            int digit = random.nextInt(10);
            stringBuilder.append(digit);
        }

        BigInteger bigInteger = new BigInteger(stringBuilder.toString());
        return bigInteger.toString();
    }


}
